//
//  ShmNoteModel.swift
//  ParsingCC
//
//  Created by ins-yangming on 2023/1/7.
//

import UIKit

class ShmBaseNoteModel : NSObject {
    var x = 0.0;
    
    func getXmlElement() -> GDataXMLElement{
        let noteElement = GDataXMLNode.element(withName: "note")!;
        return noteElement;
    }
}

class ShmNoteModel: ShmBaseNoteModel {
    var color : String?;
    var defaultx : String?;
    var defaulty : String?;
    var pitch : ShmNotePitchModel?;
    var duration : String?;
    var instrumentid : String?;
    var voice : String?;
    var type : String?;
    var stem : String?;
    var staff : String?;
    var rest = false;
    var beam = [(Int , String)]();
    var tieds : [String]?;
    var chord = false;
    var arpeggiate = false;
    var articulations = false;
    var detachedLegato = false;
    
    var fermata = false;
    var accent = false;
    var slideStart = false;
    var slideStop = false;
    var glissando = "";
    
    
    var slur = "";
    var slurNumber = "";
    
    var dots = 0;
    var tremolo = 0;
    var tremoloType = "single";
    var wavyLine = false;
    var clef = "";
    var timeModification : ShmTimeModificationModel?;
    var tuplet : ShmTupletModel?;
    var isGraceSlash = 0;
    var lyric : ShmLyricModel?;
    var accidental = "";
    var tenuto = false;
    var invertedMordent = false;
    var trillmark = false;
    var turn = false;
    
    override func getXmlElement() -> GDataXMLElement{
        let noteElement = GDataXMLNode.element(withName: "note");
//        if let color = self.color , !self.rest {
//            if let colorAttribute = GDataXMLNode.attribute(withName: "color", stringValue: color) as? GDataXMLNode {
//                noteElement?.addAttribute(colorAttribute);
//            }
//        }
//
//        if let defaultx = self.defaultx {
//            if let defaultxAttribute = GDataXMLNode.attribute(withName: "default-x", stringValue: defaultx) as? GDataXMLNode {
//                noteElement?.addAttribute(defaultxAttribute);
//            }
//        }
//
//        if let defaulty = self.defaulty , !self.rest  {
//            if let defaultxAttribute = GDataXMLNode.attribute(withName: "default-y", stringValue: defaulty) as? GDataXMLNode {
//                noteElement?.addAttribute(defaultxAttribute);
//            }
//        }
        
        if self.isGraceSlash != 0 {
            let graceElement = GDataXMLNode.element(withName: "grace");
            if self.isGraceSlash == 2 {
                if let slashAttribute = GDataXMLNode.attribute(withName: "slash", stringValue: "yes") as? GDataXMLNode {
                    graceElement?.addAttribute(slashAttribute);
                }
            }
            noteElement?.addChild(graceElement);
        }
        
        if self.chord {
            let chordElement = GDataXMLNode.element(withName: "chord");
            noteElement?.addChild(chordElement);
        }
        
        if self.rest {
            let durationElement = GDataXMLNode.element(withName: "rest");
            noteElement?.addChild(durationElement);
        }else{
            if let pitchElement = self.pitch?.getXmlElement() {
                noteElement?.addChild(pitchElement);
            }
        }
        
        
        if let duration = self.duration {
            let durationElement = GDataXMLNode.element(withName: "duration" , stringValue: duration);
            noteElement?.addChild(durationElement);
        }
        
//        if let instrumentid = self.instrumentid {
//            let instrumentElement = GDataXMLNode.element(withName: "instrument");
//            if let instrumentidAttribute = GDataXMLNode.attribute(withName: "id", stringValue: instrumentid) as? GDataXMLNode {
//                instrumentElement?.addAttribute(instrumentidAttribute);
//            }
//            noteElement?.addChild(instrumentElement);
//        }
        
        if let voice = self.voice {
            let voiceElement = GDataXMLNode.element(withName: "voice" , stringValue: voice);
            noteElement?.addChild(voiceElement);
        }
        
        if self.accidental.count != 0 {
            let accidentalElement = GDataXMLNode.element(withName: "accidental" , stringValue: self.accidental);
            noteElement?.addChild(accidentalElement);
        }
       
        if let type = self.type {
            let typeElement = GDataXMLNode.element(withName: "type" , stringValue: type);
            noteElement?.addChild(typeElement);
        }
        
        if self.dots > 0 {
            let dotElement = GDataXMLNode.element(withName: "dot");
            noteElement?.addChild(dotElement);
        }
        
        
        
        if let timeModificationElement = self.timeModification?.getXmlElement() {
            noteElement?.addChild(timeModificationElement);
        }
        
        if let stem = self.stem , !self.rest  {
            let stemElement = GDataXMLNode.element(withName: "stem" , stringValue: stem);
            noteElement?.addChild(stemElement);
        }
        
        if let staff = self.staff {
            let staffElement = GDataXMLNode.element(withName: "staff" , stringValue: staff);
            noteElement?.addChild(staffElement);
        }
        
        if self.beam.count != 0 {
            for (num , beamstring) in self.beam {
                let beamElement = GDataXMLNode.element(withName: "beam" , stringValue: beamstring);
                if let numberAttribute = GDataXMLNode.attribute(withName: "number", stringValue: "\(num)") as? GDataXMLNode {
                    beamElement?.addAttribute(numberAttribute);
                }
                noteElement?.addChild(beamElement);
            }
        }
      
        
        if let lyricElement = self.lyric?.getXmlElement() {
            noteElement?.addChild(lyricElement);
        }
        
        
        
        let notationsElement = GDataXMLNode.element(withName: "notations");
        
        if let tieds = self.tieds {
            for tied in tieds {
                let tiedElement = GDataXMLNode.element(withName: "tied");
                if let typeAttribute = GDataXMLNode.attribute(withName: "type", stringValue: tied) as? GDataXMLNode {
                    tiedElement?.addAttribute(typeAttribute);
                }
                notationsElement?.addChild(tiedElement);
            }
        }
        
        if self.arpeggiate {
            let arpeggiateElement = GDataXMLNode.element(withName: "arpeggiate");
            notationsElement?.addChild(arpeggiateElement);
        }
       
        
        if self.glissando.count != 0 {
            let glissandoElement = GDataXMLNode.element(withName: "glissando");
            if let typeAttribute = GDataXMLNode.attribute(withName: "type", stringValue: self.glissando) as? GDataXMLNode {
                glissandoElement?.addAttribute(typeAttribute);
            }
            notationsElement?.addChild(glissandoElement);
        }
       
        if self.tremolo > 0 || self.wavyLine || self.trillmark || self.turn {
            let ornamentsElement = GDataXMLNode.element(withName: "ornaments");
            if self.tremolo > 0 {
                let tremoloElement = GDataXMLNode.element(withName: "tremolo" , stringValue: "\(self.tremolo)");
                if let typeAttribute = GDataXMLNode.attribute(withName: "type", stringValue: self.tremoloType) as? GDataXMLNode {
                    tremoloElement?.addAttribute(typeAttribute);
                }
                ornamentsElement?.addChild(tremoloElement);
            }
            if self.wavyLine {
                let wavylineElement = GDataXMLNode.element(withName: "wavy-line");
                if let typeAttribute = GDataXMLNode.attribute(withName: "type", stringValue: "continue") as? GDataXMLNode {
                    wavylineElement?.addAttribute(typeAttribute);
                }
                if let yAttribute = GDataXMLNode.attribute(withName: "default-y", stringValue: "20") as? GDataXMLNode {
                    wavylineElement?.addAttribute(yAttribute);
                }
                ornamentsElement?.addChild(wavylineElement);
                
                let trillmarkElement = GDataXMLNode.element(withName: "trill-mark");
                if let yAttribute = GDataXMLNode.attribute(withName: "default-y", stringValue: "20") as? GDataXMLNode {
                    trillmarkElement?.addAttribute(yAttribute);
                }
                ornamentsElement?.addChild(trillmarkElement);
            }
            
            if self.trillmark {
                let trillmarkElement = GDataXMLNode.element(withName: "trill-mark");
                if let yAttribute = GDataXMLNode.attribute(withName: "default-y", stringValue: "20") as? GDataXMLNode {
                    trillmarkElement?.addAttribute(yAttribute);
                }
                ornamentsElement?.addChild(trillmarkElement);
            }
            if self.turn {
                let turnElement = GDataXMLNode.element(withName: "turn");
                ornamentsElement?.addChild(turnElement);
            }
            notationsElement?.addChild(ornamentsElement);
        }
        
        
        if let tupletElement = self.tuplet?.getXmlElement() {
            notationsElement?.addChild(tupletElement);
        }
        
        if self.fermata {
            let fermataElement = GDataXMLNode.element(withName: "fermata" , stringValue: "normal");
            notationsElement?.addChild(fermataElement);
        }
        
        if self.accent || self.articulations || self.tenuto || self.detachedLegato {
            let articulationsElement = GDataXMLNode.element(withName: "articulations");
            if self.accent {
                let accentElement = GDataXMLNode.element(withName: "accent");
                articulationsElement?.addChild(accentElement);
            }
            
            if self.articulations {
                let staccatoElement = GDataXMLNode.element(withName: "staccato");
                articulationsElement?.addChild(staccatoElement);
            }
            
            if self.tenuto {
                let staccatoElement = GDataXMLNode.element(withName: "tenuto");
                articulationsElement?.addChild(staccatoElement);
            }
            
            if self.detachedLegato {
                let tenutoElement = GDataXMLNode.element(withName: "detached-legato");
                articulationsElement?.addChild(tenutoElement);
            }
            notationsElement?.addChild(articulationsElement);
        }
        if self.invertedMordent {
            let ornamentsElement = GDataXMLNode.element(withName: "ornaments");
            let invertedMordentElement = GDataXMLNode.element(withName: "inverted-mordent");
            if let yAttribute = GDataXMLNode.attribute(withName: "default-y", stringValue: "10") as? GDataXMLNode {
                invertedMordentElement?.addAttribute(yAttribute);
            }
            if let yAttribute = GDataXMLNode.attribute(withName: "long", stringValue: "no") as? GDataXMLNode {
                invertedMordentElement?.addAttribute(yAttribute);
            }
            ornamentsElement?.addChild(invertedMordentElement);
            notationsElement?.addChild(ornamentsElement);
        }
        
        if self.slideStop || self.slideStart {
            let slideElement = GDataXMLNode.element(withName: "slide");
            var value = "stop";
            if self.slideStart {
                value = "start";
            }
            if let typeAttribute = GDataXMLNode.attribute(withName: "type", stringValue: value) as? GDataXMLNode {
                slideElement?.addAttribute(typeAttribute);
            }
            notationsElement?.addChild(slideElement);
        }
        
      
      
        if self.slur.count != 0 {
            let slurElement = GDataXMLNode.element(withName: "slur");
            if let typeAttribute = GDataXMLNode.attribute(withName: "number", stringValue: self.slurNumber) as? GDataXMLNode {
                slurElement?.addAttribute(typeAttribute);
            }
            if let typeAttribute = GDataXMLNode.attribute(withName: "type", stringValue: self.slur) as? GDataXMLNode {
                slurElement?.addAttribute(typeAttribute);
            }
            if let orientationAttribute = GDataXMLNode.attribute(withName: "placement", stringValue: "above") as? GDataXMLNode {
                slurElement?.addAttribute(orientationAttribute);
            }
            notationsElement?.addChild(slurElement);
        }
        
        if notationsElement?.childCount() ?? 0 > 0 {
            noteElement?.addChild(notationsElement);
        }
    
        return noteElement!;
    }
    
    
}

class ShmNotePitchModel : NSObject {
    var step = "";
    var octave = "";
    var alter = 0;
    
    func getXmlElement() -> GDataXMLElement{
        
        let pitchElement = GDataXMLNode.element(withName: "pitch");
        
        
        let stepElement = GDataXMLNode.element(withName: "step" , stringValue: self.step);
        pitchElement?.addChild(stepElement);
        
        if self.alter != 0 {
            let alertElement = GDataXMLNode.element(withName: "alter" , stringValue: "\(self.alter)");
            pitchElement?.addChild(alertElement);
        }
        
        let octaveElement = GDataXMLNode.element(withName: "octave" , stringValue: self.octave);
        pitchElement?.addChild(octaveElement);
        
      
       
        return pitchElement!;
    }
    
    
    
}

class ShmTimeModificationModel : ShmBaseNoteModel {
    var actualNotes = 3;
    var normalNotes = 2;
    var normalType = "32nd";
    
    override func getXmlElement() -> GDataXMLElement {
        
        let tupletElement = GDataXMLNode.element(withName: "time-modification");
        
        let actualElement = GDataXMLNode.element(withName: "actual-notes" , stringValue: "\(self.actualNotes)");
        tupletElement?.addChild(actualElement);
        
        let normalElement = GDataXMLNode.element(withName: "normal-notes" , stringValue: "\(self.normalNotes)");
        tupletElement?.addChild(normalElement);
        
        let normalTypeElement = GDataXMLNode.element(withName: "normal-type" , stringValue: self.normalType);
        tupletElement?.addChild(normalTypeElement);
        
      
       
        return tupletElement!;
    }
    
}

class ShmTupletModel : ShmBaseNoteModel {
    var type = "start";
    var bracket = "no";
    var number = "1";
    var y = "-20";
    var placement = "";

    override func getXmlElement() -> GDataXMLElement {
        
        let tupletElement = GDataXMLNode.element(withName: "tuplet");
        
        if let typeAttribute = GDataXMLNode.attribute(withName: "type", stringValue: self.type) as? GDataXMLNode {
            tupletElement?.addAttribute(typeAttribute);
        }
        
        if let bracketAttribute = GDataXMLNode.attribute(withName: "bracket", stringValue: self.bracket) as? GDataXMLNode {
            tupletElement?.addAttribute(bracketAttribute);
        }
        
        if let numberAttribute = GDataXMLNode.attribute(withName: "number", stringValue: self.number) as? GDataXMLNode {
            tupletElement?.addAttribute(numberAttribute);
        }
        
        if let yAttribute = GDataXMLNode.attribute(withName: "default-y", stringValue: self.y) as? GDataXMLNode {
            tupletElement?.addAttribute(yAttribute);
        }
        
        if let placementAttribute = GDataXMLNode.attribute(withName: "placement", stringValue: self.placement) as? GDataXMLNode {
            tupletElement?.addAttribute(placementAttribute);
        }
        
      
       
        return tupletElement!;
    }
}

class ShmHarmonysModel : ShmBaseNoteModel {
    var defaulty = 0;
    var rootstep = "";
    var kind = "";
    var staff = 0;
    
    override func getXmlElement() -> GDataXMLElement {
        
        let harmonyElement = GDataXMLNode.element(withName: "harmony");
        
        if let colorAttribute = GDataXMLNode.attribute(withName: "color", stringValue: "#000000") as? GDataXMLNode {
            harmonyElement?.addAttribute(colorAttribute);
        }
        
        if let defaultYAttribute = GDataXMLNode.attribute(withName: "default-y", stringValue: "\(self.defaulty)") as? GDataXMLNode {
            harmonyElement?.addAttribute(defaultYAttribute);
        }
        
        
        
        let rootElement = GDataXMLNode.element(withName: "root");
        let rootStepElement = GDataXMLNode.element(withName: "root-step" ,stringValue: self.rootstep);
        rootElement?.addChild(rootStepElement);
        harmonyElement?.addChild(rootElement);
        
        let kindElement = GDataXMLNode.element(withName: "kind" ,stringValue: self.kind);
        harmonyElement?.addChild(kindElement);
        
        let staffElement = GDataXMLNode.element(withName: "staff" ,stringValue: "\(self.staff)");
        harmonyElement?.addChild(staffElement);
       
        return harmonyElement!;
    }
  
}

class ShmPedalModel : ShmBaseNoteModel {
    
    var pedal = "";
    
    override func getXmlElement() -> GDataXMLElement {
        let directionTypeElement = GDataXMLNode.element(withName: "direction-type");
       
        
        let pedalElement = GDataXMLNode.element(withName: "pedal");
        if let defaultyAttribute = GDataXMLNode.attribute(withName: "default-y", stringValue: "-1") as? GDataXMLNode {
            pedalElement?.addAttribute(defaultyAttribute);
        }
        if let typeAttribute = GDataXMLNode.attribute(withName: "type", stringValue: pedal) as? GDataXMLNode {
            pedalElement?.addAttribute(typeAttribute);
        }
        
        if let lineAttribute = GDataXMLNode.attribute(withName: "line", stringValue: "no") as? GDataXMLNode {
            pedalElement?.addAttribute(lineAttribute);
        }
        directionTypeElement?.addChild(pedalElement);
        
        return directionTypeElement!;
            
    }
}

class ShmLyricModel : ShmBaseNoteModel {
    var defaulty = 0;
    var text = "";
    override func getXmlElement() -> GDataXMLElement {
        
        let lyricElement = GDataXMLNode.element(withName: "lyric");
        
        if let numberAttribute = GDataXMLNode.attribute(withName: "number", stringValue: "part1verse1") as? GDataXMLNode {
            lyricElement?.addAttribute(numberAttribute);
        }
        
        if let colorAttribute = GDataXMLNode.attribute(withName: "color", stringValue: "#000000") as? GDataXMLNode {
            lyricElement?.addAttribute(colorAttribute);
        }
        
        if let defaultYAttribute = GDataXMLNode.attribute(withName: "default-y", stringValue: "\(self.defaulty)") as? GDataXMLNode {
            lyricElement?.addAttribute(defaultYAttribute);
        }
        
        
        
        let textElement = GDataXMLNode.element(withName: "text" , stringValue: self.text);
        lyricElement?.addChild(textElement);
       
       
        return lyricElement!;
    }
  
}
